/**
 * Copyright(C) 2008 Matthias Braunhofer
 * All rights reserved
 *
 * Created on: 26.07.2008
*/

package it.cums.editors;

import it.cums.actions.PrintAction;
import it.cums.controller.ApplicationController;
import it.cums.model.Customer;
import it.cums.model.Customers;
import it.cums.model.Order;
import it.cums.model.OrderedProduct;
import it.cums.util.Converter;
import it.cums.util.OrderManager;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Date;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.ISaveablePart2;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.part.EditorPart;

public class OrderEditor extends EditorPart implements ISaveablePart2, PropertyChangeListener {
	public static final String ID = "it.cums.editors.OrderEditor";
	private Button saveButton;
	private Button closeButton;
	private Combo statusCombo;
	private Combo customerCombo;
	private Combo priorityCombo;
	private Text orderDateText;
	private Label orderDateErrorLabel;
	private Text deliveryDateText;
	private Label deliveryDateErrorLabel;
	private Text totalPriceText;
	private Text discountText;
	private Label discountErrorLabel;
	private Text endPriceText;
	private ProductsEditTable productsEditTable;
	private InvoicesEditTable invoicesEditTable;
	private Order order;
	private boolean changed = false;

	public OrderEditor() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public void doSave(IProgressMonitor monitor) {
		save();
		changed = false;
	}

	@Override
	public void doSaveAs() {
		// TODO Auto-generated method stub

	}

	@Override
	public void init(IEditorSite site, IEditorInput input)
			throws PartInitException {
		setSite(site);
		setInput(input);
		setPartName(input.getName());
		
		// Enabling the global print button
		PrintAction printAction = new PrintAction(((OrderEditorInput)input).getOrder());
        site.getActionBars().setGlobalActionHandler(ActionFactory.PRINT.getId(),printAction);
	
        order = ((OrderEditorInput)input).getOrder();
	}

	@Override
	public boolean isDirty() {
		// TODO Auto-generated method stub
		return changed;
	}

	@Override
	public boolean isSaveAsAllowed() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void createPartControl(Composite parent) {
		ScrolledComposite scrolledComposite = new ScrolledComposite(parent, SWT.V_SCROLL);
		Composite content = new Composite(scrolledComposite, SWT.NONE);
		content.setSize(500, 660);
		
		GridLayout layout = new GridLayout();
		layout.numColumns = 3;
		content.setLayout(layout);
		
		Composite container = new Composite(content, SWT.NONE);
		GridLayout containerLayout = new GridLayout();
		containerLayout.numColumns = 3;
		container.setLayout(containerLayout);
		saveButton = new Button(container, SWT.NONE);
		saveButton.setText("Save");
		saveButton.addSelectionListener(new SelectionListener() {
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				// TODO Auto-generated method stub	
			}

			@Override
			public void widgetSelected(SelectionEvent e) {
				if (isUserInputValid()) {
					save();
					changed = false;
					firePropertyChange(EditorPart.PROP_DIRTY);
				}
			}
		});
		
		closeButton = new Button(container, SWT.NONE);
		closeButton.setText("Close");
		closeButton.addSelectionListener(new SelectionListener() {
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				// TODO Auto-generated method stub	
			}

			@Override
			public void widgetSelected(SelectionEvent e) {
				IEditorPart current = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
				PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().closeEditor(current, true);
			}});
		
		GridData headerGrid = new GridData(GridData.FILL_HORIZONTAL);
		headerGrid.horizontalSpan = 3;
		headerGrid.verticalIndent = 15;
		
		Font boldFont = JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT); 
		Label labelBasic = new Label(content, SWT.NONE);
		labelBasic.setText("Overview");
		labelBasic.setFont(boldFont);
		labelBasic.setLayoutData(headerGrid);
		
		Label label1 = new Label(content, SWT.NONE);
		label1.setText("Status:");
		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		statusCombo = new Combo(content, SWT.READ_ONLY);
		for (String status : Order.STATUS) {
			statusCombo.add(status);
		}
		statusCombo.setLayoutData(gd);
		statusCombo.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent arg0) {
				changed = true;
			}});
		Label placeHolder = new Label(content, SWT.NONE);
		placeHolder.setText("");
		
		Label label2 = new Label(content, SWT.NONE);
		label2.setText("Customer:");
		customerCombo = new Combo(content, SWT.READ_ONLY);
		customerCombo.setLayoutData(gd);
		Customers customers = ApplicationController.getInstance().getCustomers();
		for (Customer customer : customers.getCustomers()) {
			customerCombo.add(customer.getName());
		}
		customerCombo.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent arg0) {
				changed = true;
			}});
		placeHolder = new Label(content, SWT.NONE);
		placeHolder.setText("");
		
		Label label3 = new Label(content, SWT.NONE);
		label3.setText("Priority:");
		priorityCombo = new Combo(content, SWT.READ_ONLY);
		for (String priority : Order.PRIORITY) {
			priorityCombo.add(priority);
		}
		priorityCombo.setLayoutData(gd);
		priorityCombo.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent arg0) {
				changed = true;
			}});
		placeHolder = new Label(content, SWT.NONE);
		placeHolder.setText("");
		
		Label label4 = new Label(content, SWT.NONE);
		label4.setText("Order date:");
		orderDateText = new Text(content, SWT.BORDER);
		orderDateText.setLayoutData(gd);
		orderDateText.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent arg0) {
				changed = true;
			}});
		orderDateText.addFocusListener(new FocusListener() {
			@Override
			public void focusGained(FocusEvent e) {
			}

			@Override
			public void focusLost(FocusEvent e) {
				if (!getOrderDate().equals("")) {
					if (!Converter.isDate(getOrderDate())) {
						orderDateErrorLabel.setVisible(true);
					} else {
						orderDateErrorLabel.setVisible(false);
					}
				} else {
					orderDateErrorLabel.setVisible(false);
				}
			}});
		orderDateErrorLabel = new Label(content, SWT.NONE);
		orderDateErrorLabel.setText("*");
		orderDateErrorLabel.setVisible(false);
		
		Label label5 = new Label(content, SWT.NONE);
		label5.setText("Delivery date:");
		deliveryDateText = new Text(content, SWT.BORDER);
		deliveryDateText.setLayoutData(gd);
		deliveryDateText.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent arg0) {
				changed = true;
			}});
		deliveryDateText.addFocusListener(new FocusListener() {
			@Override
			public void focusGained(FocusEvent e) {
			}

			@Override
			public void focusLost(FocusEvent e) {
				if (!getDeliveryDate().equals("")) {
					if (!Converter.isDate(getDeliveryDate())) {
						deliveryDateErrorLabel.setVisible(true);
					} else {
						deliveryDateErrorLabel.setVisible(false);
					}
				} else {
					deliveryDateErrorLabel.setVisible(false);
				}
			}});
		deliveryDateErrorLabel = new Label(content, SWT.NONE);
		deliveryDateErrorLabel.setText("*");
		deliveryDateErrorLabel.setVisible(false);
		
		Label label6 = new Label(content, SWT.NONE);
		label6.setText("Total price (Euro):");
		totalPriceText = new Text(content, SWT.BORDER);
		totalPriceText.setEditable(false);
		totalPriceText.setLayoutData(gd);
		placeHolder = new Label(content, SWT.NONE);
		placeHolder.setText("");
		
		Label label7 = new Label(content, SWT.NONE);
		label7.setText("Discount (%):");
		discountText = new Text(content, SWT.BORDER);
		discountText.setLayoutData(gd);
		discountText.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent arg0) {
				changed = true;
				if (discountText.getText().length() != 0) {
					try {
						updateEndPrice(Converter.convertToInteger(discountText.getText()));
						discountErrorLabel.setVisible(false);
					} catch (Exception e) {
						discountErrorLabel.setVisible(true);
					}
				} else {
					discountErrorLabel.setVisible(false);
				} 
			}});
		discountErrorLabel = new Label(content, SWT.NONE);
		discountErrorLabel.setText("*");
		discountErrorLabel.setVisible(false);
		
		Label label8 = new Label(content, SWT.NONE);
		label8.setText("End price (Euro):");
		endPriceText = new Text(content, SWT.BORDER);
		endPriceText.setEditable(false);
		endPriceText.setLayoutData(gd);
		placeHolder = new Label(content, SWT.NONE);
		placeHolder.setText("");
		
		Label labelProducts = new Label(content, SWT.NONE);
		labelProducts.setText("Products");
		labelProducts.setFont(boldFont);
		labelProducts.setLayoutData(headerGrid);
		
		productsEditTable = new ProductsEditTable(order);
		productsEditTable.createContents(content);
		
		Label labelInvoices = new Label(content, SWT.NONE);
		labelInvoices.setText("Invoices");
		labelInvoices.setFont(boldFont);
		labelInvoices.setLayoutData(headerGrid);
		
		invoicesEditTable = new InvoicesEditTable(order);
		invoicesEditTable.createContents(content);
		
		scrolledComposite.setContent(content);
		scrolledComposite.setExpandHorizontal(true);
		scrolledComposite.setExpandVertical(false);
		
		productsEditTable.initialize(order);
		invoicesEditTable.initialize(order);
		order.getOrderedProducts().addChangeListener(this);
		order.getInvoices().addChangeListener(this);
		initialize();
	}

	@Override
	public void setFocus() {
		// TODO Auto-generated method stub
	}
	
	private void initialize() {
		statusCombo.setText(order.getStatus());
		customerCombo.setText(order.getCustomer().getName());
		priorityCombo.setText(order.getPriority());
		if (order.getOrderDate() != null) {
			orderDateText.setText(Converter.convertToString(order.getOrderDate()));
		} else {
			orderDateText.setText("");
		}
		if (order.getDeliveryDate() != null) {
			deliveryDateText.setText(Converter.convertToString(order.getDeliveryDate()));
		} else {
			deliveryDateText.setText("");
		}
		totalPriceText.setText(String.valueOf(order.getTotalPrice()));
		discountText.setText(String.valueOf(order.getDiscount()));
		endPriceText.setText(String.valueOf(order.getEndPrice()));
		changed = false;
	}
	
	private void updateEndPrice(int discount) {
		double totalPrice = Converter.convertToDouble(getTotalPrice());
		double endPrice = totalPrice - (totalPrice * discount / 100);
		endPriceText.setText(String.valueOf(endPrice));
	}
	
	private void save() {
		int discount = Converter.convertToInteger(getDiscount());
		double totalPrice = Converter.convertToDouble(getTotalPrice());
		double endPrice = Converter.convertToDouble(getEndPrice());
		Date orderDate = null;
		if (!getOrderDate().equals("")) {
			try {
				orderDate = Converter.convertToDate(getOrderDate());
			} catch (Exception e) {
			}
		}
		Date deliveryDate = null;
		if (!getDeliveryDate().equals("")) {
			try {
				deliveryDate = Converter.convertToDate(getDeliveryDate());
			} catch (Exception e) {
			}
		}
		Customers customers = ApplicationController.getInstance().getCustomers();
		Customer c = null;
		for (Customer customer : customers.getCustomers()) {
			if (getCustomer().equals(customer.getName())) {
				c = customer;
				break;
			}
		}
		if (c.getId() != order.getCustomer().getId()) {
			order.getCustomer().getOrders().removeOrder(order);
			c.getOrders().addOrder(order);
		}
		OrderManager.getInstance().updateOrder(order, getStatus(), c, getPriority(), orderDate, deliveryDate, totalPrice, discount, endPrice);
	}
	
	@Override
	public void dispose() {
		super.dispose();
		order.getOrderedProducts().removeChangeListener(this);
		order.getInvoices().removeChangeListener(this);
	}

	@Override
	public int promptToSaveOnClose() {
		MessageDialog dialog = new MessageDialog(getEditorSite().getShell(), 
												"Save resource", 
												null, 
												"'" + getTitle() + "' has been modified. Save changes?", 
												MessageDialog.QUESTION, 
												new String[] {
												IDialogConstants.YES_LABEL, 
												IDialogConstants.NO_LABEL, 
												IDialogConstants.CANCEL_LABEL},
												0);
		final int dialogResult = dialog.open();
		
		if (dialogResult == 0) {
			if (isUserInputValid()) {
				return ISaveablePart2.YES;
			} else {
				return ISaveablePart2.CANCEL;
			}
		} else if (dialogResult == 1) {
			return ISaveablePart2.NO;
		} else {
			return ISaveablePart2.CANCEL;
		}
	}
	
	private String getDiscount() {
		return discountText.getText().trim();
	}
	
	private String getOrderDate() {
		return orderDateText.getText().trim();
	}
	
	private String getDeliveryDate() {
		return deliveryDateText.getText().trim();
	}
	
	private String getCustomer() {
		return customerCombo.getText().trim();
	}
	
	private String getTotalPrice() {
		return totalPriceText.getText().trim();
	}
	
	private String getEndPrice() {
		return endPriceText.getText().trim();
	}
	
	private String getStatus() {
		return statusCombo.getText().trim();
	}
	
	private String getPriority() {
		return priorityCombo.getText().trim();
	}
	
	private boolean isUserInputValid() {
		if (getDiscount().length() == 0) {
			return false;
		}  else {
			try {
				Converter.convertToInteger(getDiscount());
			} catch (Exception e) {
				return false;
			}
		} 
		if (getOrderDate().length() != 0) {
			try {
				Converter.convertToDate(getOrderDate());
			} catch (Exception e) {
				return false;
			}
		} 
		if (getDeliveryDate().length() != 0) {
			try {
				Converter.convertToDate(getDeliveryDate());
			} catch (Exception e) {
				return false;
			}
		} 
		return true;
	}

	@Override
	public void propertyChange(PropertyChangeEvent arg0) {
		changed = true;
		double totalPrice = 0;
		for (OrderedProduct orderedProduct : order.getOrderedProducts().getOrderedProducts()) {
			totalPrice += orderedProduct.getEndPrice();
		}
		totalPriceText.setText(String.valueOf(totalPrice));
		int discount = 0;
		if (Converter.isInteger(discountText.getText())) {
			discount = Converter.convertToInteger(discountText.getText());
		}
		double endPrice = totalPrice - (totalPrice * discount / 100);
		endPriceText.setText(String.valueOf(endPrice));
	}
}
